package com.lj.common_web.filter;

import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.lj.common.exception.CommonException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.util.concurrent.TimeUnit;

/**
 * @author luojing
 * @since 2025/5/29 16:18
 * 签名示例
 */
public class SimpleVerifySignature implements VerifySignature {

    private static final TimedCache<String, Object> timedCache = CacheUtil.newTimedCache(10 * 60 * 1000, 20 * 60 * 1000);

    @Override
    public void verify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 签名
        String sign = request.getHeader("X-Sign");
        // 随机数
        String nonce = request.getHeader("X-Nonce");
        // 时间戳(单位毫秒)
        String timestampStr = request.getHeader("X-Timestamp");
        if (StrUtil.hasBlank(sign, nonce, timestampStr)) {
            throw new CommonException("签名参数错误!");
        }
        // 时间有效期为10分钟
        long timestamp = NumberUtil.parseLong(timestampStr);
        if (Math.abs(System.currentTimeMillis() - timestamp) > TimeUnit.MINUTES.toMillis(10)) {
            throw new CommonException("请求过期");
        }
        // 防止请求重放,一个随机数只能用一次
        Object o = timedCache.get(nonce, false);
        if (o != null) {
            throw new CommonException("nonce失效");
        }
        timedCache.put(nonce, new Object());

        String body = IoUtil.readUtf8(request.getInputStream());
        // 校验签名
        if (!DigestUtil.md5Hex(nonce + timestampStr + body).equals(sign)) {
            throw new CommonException("签名错误!");
        }
    }
}
